home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Games of Daze
/
Infomagic - Games of Daze (Summer 1995) (Disc 1 of 2).iso
/
x2ftp
/
msdos
/
libs
/
graphsrc
/
g31.c
< prev
next >
Wrap
C/C++ Source or Header
|
1990-03-24
|
14KB
|
364 lines
/*
g3 - three dimensional graphics interface
history...
24 Mar 90 Added function prototypes
13 Jul 89 Hid debugging code behind #ifdef's
4 Jul 85 Renamed to set_linestyle(), set_linewidth, etc. per
revised CORE standard. Corrected clipping parameters for small viewports.
21 Apr 85 Removed declarations of draw_line and erase_line, since
they weren't used.
18 Apr 85 Initializing linestyle and linewidth.
9 Mar 85 hid (*erase_line)() references behind #ifdef's. changed
init() references to init_graphics(), removed inquire_current_color().
bugs... (from Jim Knutson)
Also, I noticed some interesting problems when trying to get it to
compile. First of all, the debugging print code takes up a lot of space.
I couldn't get g31.c to compile because it said function too big. I got
around the problem by #ifdefing the debugging prints rather than using
the C if construct. Secondly, I noticed that there are a lot of externs
in g32.c that are defined there as well as in g.h. Not only that
but g32.c has some externs that are declared twice and some that are
ifdefed but are in g.h anyway (notable erase_line).
*/
#include <stdio.h>
#include <math.h>
#define DEFAULT_MODE 0
/* variables defined in file of hardware-dependent
routines, such as gz.c */
extern int pixels_wide,pixels_high; /* device size in pixels */
extern double best_width,best_height; /* device height/width (proportional
to actual dimensions in inches, but one of these *must* be 1,
and the other must be in the range 0 to 1) */
extern clear_graphics(); /* clears screen */
extern init_graphics();
extern finish_graphics();
/* variables */
int debugging=0;
int
clipping=0, /* nonzero if clipping is enabled */
front_clipping=0, /* nonzero if front clipping is enabled */
back_clipping=0, /* nonzero if back clipping is enabled */
graphics_level=1, /* level of CORE graphics requested */
initialized = 0, /* nonzero after output driver is initialized */
mode = 0,
need_depth, /* nonzero if depth must be calculated (perspective
projection or depth clipping */
num_segments=0, /* number of segments that still exist */
persp_proj=0, /* nonzero if perspective projection requested */
segment_open=0, /* nonzero if a segment is open */
wmin1,wmax1, /* minimum & maximum x values in device coordinates */
wmin2,wmax2; /* minimum & maximum y values in device coordinates */
double
aspect_ratio, /* height/width ratio of display */
left_handed=1., /* 1 for LH world coordinate system, -1 for RH */
vdist=0., /* distance from viewpoint along view plane normal to
viewplane */
c_bottom[4],c_top[4], /* clip vectors...if x is visible, then */
c_left[4],c_right[4], /* x[0]*c[0] + x[1]*c[1] + x[2]*c[2] > c[3] */
c_near[4],c_far[4], /* for c equal to each of these six arrays */
cur_x, cur_y, cur_z, /* current position (world coordinates) */
uu, vv, nn, /* current position (viewport coordinates) */
norm1=0., norm2=0., norm3=1., /* view plane normal */
p1=0., p2=0., p3=1., /* direction for parallel projection, or
center of projection */
up1=0., up2=1., up3=0., /* view up vector */
vrp1=0., vrp2=0., vrp3=0., /* view reference point */
umin=0., umax=1., /* window in world coordinates */
vmin=0., vmax=1.,
wmin=0., wmax=1.,
vp_xmin=0., vp_xmax=1., /* requested viewport in NDC */
vp_ymin=0., vp_ymax=1.,
vp_zmin=0., vp_zmax=1.,
ndc_width=1., ndc_height=1., ndc_depth=1., /* requested limits on NDC values */
rot11, rot12, rot13, rot14, /* rotation & projection matrix */
rot21, rot22, rot23, rot24,
rot31, rot32, rot33, rot34; /* (3rd row is for perspective projections) */
/* CORE graphics routines */
/* clip_window - enable clipping if i is nonzero */
clip_window(i) int i; {clipping=i; reset_line();}
/* close_temporary_segment - close the current segment */
close_temporary_segment()
{ segment_open=0;
}
/* coordinate_system_type - set to RH coordinates if i is nonzero */
coordinate_system_type(i) int i; {left_handed=(i?-1.:1.);
}
/* create_temporary_segment - create a new segment */
create_temporary_segment()
{ static double
skew13, skew23, skew33,
size, p_lnth,
vp11, vp22, vp13, vp23, vp14, vp24, vp33,
n1, n2, n3, n4, /* view plane unit normal */
u1, u2, u3, u4, /* horizontal unit vector in rotated system */
v1, v2, v3, v4, /* vertical unit vector in rotated system */
width_used,height_used,
xscale,yscale;
#ifdef DEBUG
if(debugging)
{printf("persp_proj = %d, p = (%f,%f,%f)\n",persp_proj,p1,p2,p3);
}
#endif
set_linestyle(0); /* SOLID line */
set_linewidth(1);
segment_open=1;
num_segments++;
size=sqrt(norm1*norm1 + norm2*norm2 + norm3*norm3);
if(size==0.) /* ensure finite vpn */
{puts("view plane normal has no length\n");
n1=0.; n2=0.; n3=1.;
}
else {n1=norm1/size; n2=norm2/size; n3=norm3/size;}
if((up1==0.)&&(up2==0.)&&(up3==0.)) /* ensure finite up vector */
{puts("up vector has no length\n");
up1=0.; up2=1.; up3=0.;
}
#ifdef DEBUG
if(debugging) printf("up = (%10f,%10f,%10f) \n",up1,up2,up3);
#endif
u1=up2*n3 - up3*n2; /* find horizontal unit vector u in */
u2=up3*n1 - up1*n3; /* rotated system = up CROSS n */
u3=up1*n2 - up2*n1;
size=sqrt(u1*u1 + u2*u2 + u3*u3);
if(size==0.)
{puts("view plane normal and up vector are in same direction\n");
u1=1.; u2=0.; u3=0.; v1=0.; v2=1.; v3=0.;
}
else
{u1=u1/size; u2=u2/size; u3=u3/size;
v1=n2*u3 - n3*u2; /* find vertical unit vector v in */
v2=n3*u1 - n1*u3; /* rotated system = n CROSS u */
v3=n1*u2 - n2*u1;
size=sqrt(v1*v1 + v2*v2 + v3*v3); /* u & n finite & normal, */
v1=v1/size; v2=v2/size; v3=v3/size; /* so size is nonzero */
}
p_lnth=sqrt(p1*p1 + p2*p2 + p3*p3);
if(p_lnth==0.) /* ensure p vector has finite length */
{puts("parallel/perspective vector has no length\n");
p1=0.; p2=0.; p3=1.; p_lnth=1.;
}
/* For parallel projection, the transformation is...
(rot11 rot12 rot13 rot14) (x)
(rot21 rot22 rot23 rot24) (y) =
(z)
(1)
(u1 u2 u3 0) (1 -vrp1) (x)
(1 0 skew13 0) (v1 v2 v3 0) ( 1 -vrp2) (y)
(vp11 0 vp13) (0 1 skew23 0) (n1 n2 n3 0) ( 1 -vrp3) (z)
( 0 vp22 vp23) (0 0 0 1) (0 0 0 1) ( 1 ) (1)
...where the rightmost matrix shifts the input point to account for the view
reference point location, the next rotates it to the u, v, n coordinates, the
"skew" matrix accounts for oblique projection, and the "vp" matrix transforms
to the viewport in device coordinates.
For perspective projections, the transformation is:
(r) (a/c) (a) (rot11 rot12 rot13 rot14) (x)
(s) = (b/c), (b) = (rot21 rot22 rot23 rot24) (y) =
(c) (rot31 rot32 rot33 rot34) (z)
(1)
( 1 -vrp1) (x)
(vp11 0 vp13) ( 1 skew13 ) ( u1 u2 u3 u4 ) ( 1 -vrp2) (y)
( 0 vp22 vp23) ( 1 skew23 ) ( v1 v2 v3 v4 ) ( 1 -vrp3) (z)
( 0 0 1 ) ( skew33 ) ( n1 n2 n3 n4 ) ( 1 ) (1)
c is the depth coordinate, scaled so that 0 is the same depth as the center of
perspective, and 1 is the depth of the viewplane.
*/
u4=-(u1*p1 + u2*p2 + u3*p3);
v4=-(v1*p1 + v2*p2 + v3*p3);
skew13=u4;
skew23=v4;
aspect_ratio=best_height/best_width;
if((0.>=ndc_width)|(0.>=ndc_height))
{puts("invalid ndc coordinate limits");
ndc_width=ndc_height=1.;
}
if((-.001>vp_xmin)||(vp_xmin>=vp_xmax)||(vp_xmax>ndc_width+.001)||
(-.001>vp_ymin)||(vp_ymin>=vp_ymax)||(vp_ymax>ndc_height+.001))
{puts("invalid viewport");
printf("\n need 0 <= %f=vp_xmin < %f=vp_xmax <= %f=ndc_width",
vp_xmin, vp_xmax, ndc_width);
printf("\n and 0 <= %f=vp_ymin < %f=vp_ymax <= %f=ndc_height",
vp_ymin, vp_ymax, ndc_height);
vp_xmin=0.; vp_xmax=ndc_width;
vp_ymin=0.; vp_ymax=ndc_height;
}
if(ndc_height/ndc_width>aspect_ratio) /* user isn't using all the width */
{height_used=(double)pixels_high-1;
width_used=(double)(pixels_wide-1)
*aspect_ratio*ndc_width/ndc_height;
}
else /* user isn't using all the height */
{height_used=(double)(pixels_high-1)
/aspect_ratio/(ndc_width/ndc_height);
width_used=(double)pixels_wide-1;
}
xscale=width_used/ndc_width;
yscale=height_used/ndc_height;
wmin1=(int)(xscale*vp_xmin);
wmax1=(int)(xscale*vp_xmax);
wmin2=(int)(yscale*(ndc_height-vp_ymax));
wmax2=(int)(yscale*(ndc_height-vp_ymin));
vp11= xscale*(vp_xmax-vp_xmin)/(umax-umin);
vp22=-yscale*(vp_ymax-vp_ymin)/(vmax-vmin);
vp14=vp13= xscale*(umax*vp_xmin-umin*vp_xmax)/(umax-umin);
vp24=vp23=-yscale*(vmax*vp_ymin-vmin*vp_ymax)/(vmax-vmin) + height_used;
#ifdef DEBUG
if(debugging)
{printf("vp = %10f %10f \n",vp11,vp13);
printf( " %10f %10f \n",vp22,vp23);
printf( " 1 \n");
}
#endif
if(persp_proj) /* perspective projection */
{n4=-(n1*p1 + n2*p2 + n3*p3);
if(fabs(n4)<.001*p_lnth)
{puts("can\'t project view reference point onto view plane \n");
n4=1.;
}
skew13=-skew13/n4;
skew23=-skew23/n4;
if(fabs(n4+vdist)<1.e-10)
{puts("center of projection is in view plane \n");
vdist=0.;
}
vp33=skew33=1./(n4+vdist);
vp13=vp11*skew13 + vp13*skew33;
vp23=vp22*skew23 + vp23*skew33;
/* vp is now the product of the 1st 2 matrices */
rot11= vp11*u1 + vp13*n1;
rot12= vp11*u2 + vp13*n2;
rot13=(vp11*u3 + vp13*n3) *left_handed;
rot14= vp11*u4 + vp13*n4;
rot21= vp22*v1 + vp23*n1;
rot22= vp22*v2 + vp23*n2;
rot23=(vp22*v3 + vp23*n3) *left_handed;
rot24= vp22*v4 + vp23*n4;
rot31= vp33*n1;
rot32= vp33*n2;
rot33= vp33*n3 *left_handed;
rot34= vp33*n4;
rot14= rot14 - (rot11*vrp1 + rot12*vrp2 + rot13*vrp3);
rot24= rot24 - (rot21*vrp1 + rot22*vrp2 + rot23*vrp3);
rot34= rot34 - (rot31*vrp1 + rot32*vrp2 + rot33*vrp3);
c_bottom[0]=0.; /* (umin,vmin,1) CROSS (umax,vmin,1) */
c_bottom[1]=umin-umax;
c_bottom[2]=vmin*(umin-umax);
c_bottom[3]=0.;
c_top[0]=0.; /* (umax,vmax,1) CROSS (umin,vmax,1) */
c_top[1]=umin-umax;
c_top[2]=vmax*(umax-umin);
c_top[3]=0.;
c_left[0]=vmax-vmin; /* (umin,vmax,1) CROSS (umin,vmin,1) */
c_left[1]=0.;
c_left[2]=umin*(vmin-vmax);
c_left[3]=0.;
c_right[0]=vmin-vmax; /* (umax,vmin,1) CROSS (umax,vmax,1) */
c_right[1]=0.;
c_right[2]=umax*(vmax-vmin);
c_right[3]=0.;
}
else /* parallel projection */
{
/*
vp13=vp11*skew13;
vp23=vp22*skew23;
rot11= vp11*u1 + vp13*n1;
rot21= vp22*v1 + vp23*n1;
rot12= vp11*u2 + vp13*n2;
rot22= vp22*v2 + vp23*n2;
rot13=(vp11*u3 + vp13*n3) *left_handed;
rot23=(vp22*v3 + vp23*n3) *left_handed;
rot14=-(rot11*vrp1 + rot12*vrp2 + rot13*vrp3) + vp14;
rot24=-(rot21*vrp1 + rot22*vrp2 + rot23*vrp3) + vp24;
*/
rot11=(u1 + skew13*n1)*vp11;
rot21=(v1 + skew23*n1)*vp22;
rot12=(u2 + skew13*n2)*vp11;
rot22=(v2 + skew23*n2)*vp22;
rot13=(u3 + skew13*n3)*vp11 *left_handed;
rot23=(v3 + skew23*n3)*vp22 *left_handed;
rot14=-(rot11*vrp1 + rot12*vrp2 + rot13*vrp3) + vp13;
rot24=-(rot21*vrp1 + rot22*vrp2 + rot23*vrp3) + vp23;
}
c_near[0]=c_near[1]=0.; c_near[2]=1.; c_near[3]=wmin;
c_far[0]=c_far[1]=0.; c_far[2]=-1.; c_far[3]=-wmax;
#ifdef DEBUG
if(debugging)
{printf("skew = 1 %10f \n",skew13);
printf(" 1 %10f \n",skew23);
printf(" %10f \n",skew33);
printf("u,v,n= %10f %10f %10f %10f \n",u1,u2,u3,u4);
printf(" %10f %10f %10f %10f \n",v1,v2,v3,v4);
printf(" %10f %10f %10f %10f \n",n1,n2,n3,n4);
printf("vrp = 1 %10f \n",-vrp1);
printf(" 1 %10f \n",-vrp2);
printf(" 1 %10f \n",-vrp3);
printf(" 1 \n");
printf("rot= %10f %10f %10f %10f \n",rot11,rot12,rot13,rot14);
printf(" %10f %10f %10f %10f \n",rot21,rot22,rot23,rot24);
printf(" %10f %10f %10f %10f \n",rot31,rot32,rot33,rot34);
printf("width_used= %5.1f height_used= %5.1f \n",
width_used, height_used);
printf("xscale= %5f yscale= %5f \n",xscale, yscale);
getchar();
show_clipping();
}
#endif
move_abs_3(0.,0.,0.);
}
#ifdef DEBUG
show_clipping()
{ printf("umin = %f vmin = %f wmin = %f \n",umin,vmin,wmin);
printf("umax = %f vmax = %f wmax = %f \n",umax,vmax,wmax);
printf("vp_xmin = %f vp_ymin = %f vp_zmin = %f \n",vp_xmin,vp_ymin,vp_zmin);
printf("vp_xmax = %f vp_ymax = %f vp_zmax = %f \n",vp_xmax,vp_ymax,vp_zmax);
printf("ndc_width = %f ndc_height = %f ndc_depth = %f \n",ndc_width,ndc_height,ndc_depth);
printf("wmin1 = %d wmin2 = %d \n",wmin1,wmin2);
printf("wmax1 = %d wmax2 = %d \n",wmax1,wmax2);
printf("c_left = (%10f,%10f,%10f,%10f) \n",c_left[0],c_left[1],c_left[2],c_left[3]);
printf("c_right = (%10f,%10f,%10f,%10f) \n",c_right[0],c_right[1],c_right[2],c_right[3]);
printf("c_bottom = (%10f,%10f,%10f,%10f) \n",c_bottom[0],c_bottom[1],c_bottom[2],c_bottom[3]);
printf("c_top = (%10f,%10f,%10f,%10f) \n",c_top[0],c_top[1],c_top[2],c_top[3]);
printf("c_near = (%10f,%10f,%10f,%10f) \n",c_near[0],c_near[1],c_near[2],c_near[3]);
printf("c_far = (%10f,%10f,%10f,%10f) \n",c_far[0],c_far[1],c_far[2],c_far[3]);
getchar();
}
#endif
/* initialize_core - initialize everything */
initialize_core(out,in,dimension)
int out, /* 0=basic 1=buffered 2=dynamic a 3=dynamic b 4=dynamic c */
in, /* 0=none 1=synchronous 2=complete */
dimension; /* 2=2D 3=3D */
{ if(out>1 || in>1)
{puts("WARNING: no retained segments or input primitives supported\n");
getchar();
}
if(!initialized) init_graphics(DEFAULT_MODE);
initialized=1;
}